package com.leyou.user.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.user.entity.User;
import com.leyou.user.entity.UserDTO;
import com.leyou.user.mapper.UserMapper;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.leyou.common.constants.MQConstants.Exchange.SMS_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKey.VERIFY_CODE_KEY;

@Service
@Transactional
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    private static final String MSG_CHECK_CODE_PRE = "MSG_CHECK_CODE_PRE";

    public Boolean checkUsernameAndPhone(String data, Integer type) {
        try{
            User record = new User();
            switch (type){
                case 1:
                    record.setUsername(data);
                    break;
                case 2:
                    record.setPhone(data);
                    break;
                default:
                    throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
            }
            int count = userMapper.selectCount(record);
            //如果没有查询到返回true
            return count == 0;  //0==0 就是true啊 老哥 想啥呢 1==0 false
        }catch (Exception e){
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
    }

    public void sendCheckCode(String phone) {
        //生成短信验证码
        String code = RandomStringUtils.randomNumeric(6);
        //向redis中存放验证码
        redisTemplate.opsForValue().set(MSG_CHECK_CODE_PRE + phone,code,24, TimeUnit.HOURS);
        //封装发送的MQ消息内容
        Map<String,String> checkCodeMap = new HashMap<>();
        checkCodeMap.put("phone",phone);
        checkCodeMap.put("code",code);
        //向指定队列中发送MQ消息
        amqpTemplate.convertAndSend(SMS_EXCHANGE_NAME, VERIFY_CODE_KEY, checkCodeMap);
    }

    public void register(User user, String code, String confirmPassword) {
        try{
            //验证验证码是否正确
            if(!StringUtils.equals(code,redisTemplate.opsForValue().get(MSG_CHECK_CODE_PRE + user.getPhone()))){
                throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
            }
            //验证密码是否正确
            if(!StringUtils.equals(confirmPassword,user.getPassword())){
                throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
            }
            //对密码进行加密
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            //保存数据
            userMapper.insertSelective(user);
        }catch (Exception e){
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }

    }

    public UserDTO findByUsernameAndPassword(String username, String password) {
        try {
            //先判断用户名是否正确
            User record = new User();
            record.setUsername(username);
            User userInfo = userMapper.selectOne(record);   //如果在数据库中查不到,势必会报异常,捕获异常,抛出
            //再判断密码是否正确
            boolean matches = passwordEncoder.matches(password, userInfo.getPassword());
            if(matches){
                return BeanHelper.copyProperties(userInfo, UserDTO.class);
            }
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }catch (Exception e){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
    }
}
